<script setup lang="ts" name="GoodsSku">
import { GoodsInfo, Value, Spec } from '@/types/goods'
import bwPowerSet from '@/utils/power-set'
// console.log(bwPowerSet(['黑色', '20cm']))
// 接收商品信息
const props = defineProps<{
  goods: GoodsInfo
  skuId?: string
}>()
const emit = defineEmits<{
  (e: 'selectedGoods', skuId: string): void
}>()
// 组合点击梳理
// 刚才实现的是按钮默认禁用 有些商品规格默认就没货
// 现在点击按钮组合禁用  组合点击各个规格后 也需要去路径字典中匹配, 看是否要禁用哪些按钮
// 用户在选择商品规格的时候 不一定是按着顺序从上到下去点击 30cm★日本★蓝色    日本★30cm★蓝色 都不在字典里面 但是字典中是有 蓝色★日本★30cm
// 解决 不论用户怎么点击 保证 收集到用户点击的规格顺序 一定是和字典中的顺序一样 保证数组的顺序
// 4. 保证点击规格的数据的顺序
const orderArr = () => {
  // 循环specs, 拿到每一个被选中的按钮有序放在数组中
  const arr: string[] = ['', '', '']
  props.goods.specs.forEach((spec, index) => {
    const btn = spec.values.find(btn => btn.selected)
    if (btn) {
      arr[index] = btn.name
    } else {
      arr[index] = ''
    }
  })
  return arr
}
// 1. 点击选中功能
const changeSelected = (subItem: Value, item: Spec) => {
  if (subItem.disabled) return // 已经被禁用禁止点击
  // console.log(item)
  // 判断selected字段, 设置selected的值为true / false
  if (subItem.selected) {
    subItem.selected = false
  } else {
    // 干掉所有人, 留下我自己
    item.values.forEach(obj => obj.selected = false)
    // 排他
    subItem.selected = true
  }
  // 点击的时候也要禁用按钮
  defaultDisabledSpec()
  // 选择完一个完整的规格后 记录skuId 传递给父组件 =>加入购物车....
  const selectArr = orderArr()
  // 1. 过滤数组,看是否是有空元素
  const res = selectArr.filter(value => value)
  console.log(res)
  // 2. 如果过滤出来的数组长度等于props.goods.specs.length  才要记录skuId 
  if (res.length === props.goods.specs.length) {
    // 3.将res处理成字符串去字典中找
    const key = res.join('★')
    const skuId = pathMap[key][0]//找到了完整规格的skuId
    emit('selectedGoods', skuId)
  } else {
    emit('selectedGoods', '')
  }
}

// 2. 求路径字典 ==> 按钮默认禁用和组合禁用
const getMap = () => {
  // const object: any  = {}
  const object: { [key: string]: string[] } = {}
  // console.log(props.goods.skus) //所有的sku集合
  // 2.1. 过滤掉无效的sku情况(保留库存>0的sku)
  const skus = props.goods.skus.filter(item => item.inventory > 0)
  // console.log(skus) // 有效的sku集合
  // 2.2 将有效的skus中的specs的每一项的valueName收集到各自的数组中 ==> 求子集
  skus.forEach(sku => { // sku每一项有效的sku
    // console.log(sku)
    const arr = sku.specs.map(spec => spec.valueName)
    // console.log(arr)
    // 2.3 基于收集到的数组求一个子集
    const sets = bwPowerSet(arr)
    // console.log(sets)
    // 2.4 循环子集 向字典中存储数据
    sets.forEach(set => {
      // 2.5 将每一个set转换成字符串 [] => ''
      const key = set.join('★')
      // console.log(key)
      // 2.6 往object对象中追加(如果对象中没有这个key,开辟一个key, 如果有key,直接追加值)
      // if (object.hasOwnProperty(key)) {
      if (object[key]) {
        // 有就累加
        object[key].push(sku.id)
      } else {
        // 没有将这个key对应的值设置为[skuid]
        object[key] = [sku.id]
      }
    })
  })
  return object
}
const pathMap = getMap() // 路径字典
console.log(pathMap)
// 3. 默认按钮规格的禁用
// 取到所有的规格按钮 去 路径字典中查找, 看是否有某个按钮不存在路径字典对象中, 不存在就禁用
const defaultDisabledSpec = () => {
  // 只要点击 得到一个有序的数组
  const arr = orderArr() // ['', '', '10cm'] 
  // console.log(arr)
  props.goods.specs.forEach((spec, index) => { // 每一行
    spec.values.forEach(btn => { // 每一个按钮对象
      // console.log(btn.name) // 每个按钮的文本,检测这个文本是否在路径字典中
      const newArr = [...arr] // ['', '', '10cm'] 
      newArr[index] = btn.name
      // console.log(newArr)
      const key = newArr.filter(item => item).join('★')
      // console.log(key)
      if (pathMap[key]) {
        btn.disabled = false
      } else {
        btn.disabled = true
      }
    })
  })
}
// 页面一加载调用一次
defaultDisabledSpec()

// 5. 默认选中规格
const defaultCheckedBtn = () => {
  // 5.1 没传skuId 不选中
  if (!props.skuId) return
  // 5.2 基于传过来的skuId 默认规格的勾选
  // 5.2.1 从goods.skus数组中查找那一项sku
  const sku = props.goods.skus.find(sku => sku.id === props.skuId)
  console.log(sku)
  // 5.3 找到了这个sku,这个sku中有specs(数组) 记录了各个规格
  if (sku) {
    props.goods.specs.forEach((spec, index) => {
      console.log(spec)
      spec.values.forEach(btn => { // 每个按钮所在的对象
        // console.log(value)
        // console.log(sku.specs[index].valueName)
        if (btn.name === sku.specs[index].valueName) {
          btn.selected = true
        }
      })
    })
  }
}
defaultCheckedBtn()

</script>
<template>
  <div class="goods-sku">
    <dl v-for="item in goods.specs" :key="item.name">
      <dt>{{ item.name }}</dt>
      <dd>
        <!-- selected类名表示选中  disabled类名表示禁用 -->
        <template v-for="subItem in item.values" :key="subItem.name">
          <img :class="{ selected: subItem.selected, disabled: subItem.disabled }" v-if="subItem.picture"
            :src="subItem.picture" @click="changeSelected(subItem, item)" />
          <span :class="{ selected: subItem.selected, disabled: subItem.disabled }" v-else
            @click="changeSelected(subItem, item)">{{ subItem.name
            }}</span>
        </template>
      </dd>
    </dl>
  </div>
</template>

<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;

  &.selected {
    border-color: @xtxColor;
  }

  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}

.goods-sku {
  padding-left: 10px;
  padding-top: 20px;

  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;

    dt {
      width: 50px;
      color: #999;
    }

    dd {
      flex: 1;
      color: #666;

      >img {
        width: 50px;
        height: 50px;
        margin-top: 5px;
        .sku-state-mixin ();
      }

      >span {
        display: inline-block;
        height: 30px;
        line-height: 30px;
        padding: 0 20px;
        margin-top: 5px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
